<?php

namespace App\Listeners;

use App\Events\DeviceStatusChange;
use App\Events\OrderStatusChange;
use App\Events\WebAppOrderChange;
use App\Tables\Device;
use App\Tables\Order as OrderTable;
use Order;
use Carbon\Carbon;
use Log;
use Redis;


class OrderEventSubscriber
{
    /**
     * 处理订单生成后逻辑, 发送设备开启命令
     * @param $event
     */
    public function onCreateOrder($event)
    {
        $cmds = [
            1 => 'a',
            2 => 'b',
            3 => 'c',
            4 => 'd',
            5 => 'e',
            6 => 'f'
        ];
        $p_key = substr($event->order->port, 1);
        $cmd = $cmds[$p_key];

        $data = [
            'user' => 'user',
            'device_sn' => $event->order->device_sn,
            'cmd' => "{$event->order->order_sn};on{$cmd}"
        ];

        Redis::lpush('order-device-start', serialize($data));
    }

    /**
     * 发送设备停止指令
     * @param $event
     */
    public function onOrderStop($event)
    {
        $cmds = [
            1 => 'a',
            2 => 'b',
            3 => 'c',
            4 => 'd',
            5 => 'e',
            6 => 'f'
        ];
        $p_key = substr($event->order->port, 1);
        $cmd = $cmds[$p_key];

        $data = [
            'user' => 'user',
            'device_sn' => $event->order->device_sn,
            'cmd' => "{$event->order->order_sn};of{$cmd}"
        ];

        Redis::lpush('order-device-stop', serialize($data));
    }

    /**
     * 订单状态变化
     * @param $event
     */
    public function onOrderStatusChange($event)
    {
        $order = OrderTable::where('order_sn', $event->order_sn)->first();

        Log::debug('订单状态变化', [$event->order_sn, $event->status]);

        if (!empty($order)) {
            if ($event->status == 'start') {
                if ($order->status == 'wait_pay') {
                    $order->status = 'service';
                    $order->service_start_at = Carbon::now();
                    if ($order->save()) {
                        // 推送订单状态变化给前端
                        event(new WebAppOrderChange($order));
                    } else {
                        Log::error('订单开始服务失败', ['order_sn' => $event->order_sn]);
                    }
                } else {
                    Log::error('订单开始服务失败, 订单不在待服务状态', ['order_sn' => $event->order_sn, 'status' => $order->status_text]);
                }
            } else if (in_array($event->status, ['stop', 'stop2'])) {
                if ($order->status == 'service') {
                    $order->service_end_at = Carbon::now();

                    /**
                     * 不足一分钟按一分钟计算
                     */
                    $consume_duration = $order->service_end_at->diffInMinutes($order->service_start_at);
                    $order->consume_duration = $consume_duration >= 1 ? $consume_duration : 1;

                    if ($order->save()) {
                        $device = Device::where('device_sn', $order->device_sn)->first();
                        if (!empty($device)) {
                            $ports = $device->ports;
                            $ports[$order->port] = 0;

                            $device->ports = $ports;
                            $res = $device->save();
                            if ($res === false) {
                                Log::error('端口释放失败', ['order_sn' => $event->order_sn]);
                            } else {
                                // 通知前端页面更改状态
                                event(new DeviceStatusChange($device));

                                // 判断是否大功率
                                $superpower = false;
                                if ($event->status == 'stop2') {
                                    $superpower = true;
                                }
                                Order::orderEnded($event->order_sn, $superpower);
                            }
                        }
                    } else {
                        Log::error('订单结束服务失败', ['order_sn' => $event->order_sn]);
                    }
                } else {
                    Log::error('订单不在服务中-停止计费失败', ['order_sn' => $event->order_sn]);
                }
            } else {
                Log::debug('订单状态变化-不在需要处理状态中', [$event->order_sn, $event->status]);
            }
        } else {
            Log::debug('订单状态变化处理-订单信息不存在', [$event->order_sn, $event->status]);
        }
    }

    /**
     * 设备进入故障模式
     * @param $event
     */
    public function onDeviceError($event)
    {
        /**
         * 设备进入故障模式
         */
        $device = Device::where('device_sn', $event->device_sn)->first();
        if (!empty($device)) {
            // 修改设备状态
            $device->status = 'fault';
            $device->ports = [ 'p1' => 0, 'p2' => 0, 'p3' => 0, 'p4' => 0, 'p5' => 0, 'p6' => 0];
            if ($device->save()) {
                // 通知前端页面更改状态
                event(new DeviceStatusChange($device));

                /**
                 * 查询出设备所有的未停止计费的订单
                 */
                $orders = OrderTable::where('device_sn', $event->device_sn)->where('status', 'service')->get(['order_sn']);
                foreach ($orders as $order) {
                    event(new OrderStatusChange($order->order_sn, 'stop'));
                }

                Log::debug('设备已进入故障模式', [$event->device_sn, $event->error_msg]);
            } else {
                Log::debug('设备进入故障模式失败', [$event->device_sn, $event->error_msg]);
            }
        } else {
            Log::debug('设备故障-设备信息不存在', [$event->device_sn, $event->error_msg]);
        }
    }

    /**
     * 设备进入故障模式
     * @param $event
     */
    public function onDeviceStatusMessageProcess($event)
    {
        /**
         * 设备进入故障模式
         */
        $device = Device::where('device_sn', $event->device_sn)->first();
        if (!empty($device)) {
            if ('online' == $event->status) { // 设备上线
                $device->status = 'online';
                $device->ports = [ 'p1' => 0, 'p2' => 0, 'p3' => 0, 'p4' => 0, 'p5' => 0, 'p6' => 0];
                if ($device->save()) {
                    // 通知前端页面更改状态
                    event(new DeviceStatusChange($device));
                    Log::debug('设备状态消息处理-设备进入上线模式', [$event->device_sn, $event->status]);
                } else {
                    Log::debug('设备状态消息处理-设备进入上线模式失败', [$event->device_sn, $event->status]);
                }
            } else if ('offline' == $event->status) { // 设备离线
                // 修改设备状态
                $device->status = 'offline';
                if ($device->save()) {
                    // 通知前端页面更改状态
                    event(new DeviceStatusChange($device));
                    /**
                     * 查询出设备所有的未停止计费的订单
                     */
                    $orders = OrderTable::where('device_sn', $event->device_sn)->where('status', 'service')->get(['order_sn']);
                    foreach ($orders as $order) {
                        event(new OrderStatusChange($order->order_sn, 'stop'));
                    }

                    Log::debug('设备状态消息处理-设备进入离线模式', [$event->device_sn, $event->status]);
                } else {
                    Log::debug('设备状态消息处理-设备进入离线模式失败', [$event->device_sn, $event->status]);
                }
            }
        } else {
            Log::debug('设备状态消息处理-设备信息不存在', [$event->device_sn, $event->status]);
        }
    }

    /**
     * 为订阅者注册监听器。
     * @param Illuminate\\Events\\Dispatcher $events
     */
    public function subscribe($events)
    {
        $events->listen(
            'App\Events\CreateOrder',
            'App\Listeners\OrderEventSubscriber@onCreateOrder'
        );

        $events->listen(
            'App\Events\OrderStop',
            'App\Listeners\OrderEventSubscriber@onOrderStop'
        );

        $events->listen(
            'App\Events\DeviceError',
            'App\Listeners\OrderEventSubscriber@onDeviceError'
        );

        $events->listen(
            'App\Events\DeviceStatusMessageProcess',
            'App\Listeners\OrderEventSubscriber@onDeviceStatusMessageProcess'
        );

        $events->listen(
            'App\Events\OrderStatusChange',
            'App\Listeners\OrderEventSubscriber@onOrderStatusChange'
        );
    }
}
